import { pauseTracking, resumeTracking, track } from '../effect/track'
import { reactive } from '../reactive';
import { isObject, RAW, toRaw, TrackOpTypes } from '../utils';

const arrayInstrumentations: Record<string, Function> = {};

// 数组查找的方法
; (['includes', 'indexOf', 'lastIndexOf'] as const).forEach((element: any) => {
  arrayInstrumentations[element] = function (this: unknown[], ...args: unknown[]) {
    // 获取原始数组
    const arr = toRaw(this) as any;
    // 遍历数组索引，收集依赖
    for (let i = 0, l = this.length; i < l; i++) {
      track(arr, TrackOpTypes.GET, i + '');
    }
    // 先找一遍，// 调用原始数组上的方法（可能是代理对象），并传入原始的参数
    const res = arr[element](...args);
    if (res === -1 || res === false) {
      // 如果结果为 -1 或 false，使用原始值再找一遍
      return arr[element](...args.map(toRaw));
    } else {
      return res;
    }
  }
})

// 更改数组的方法, 不收集length
; (['push', 'pop', 'shift', 'unshift', 'splice'] as const).forEach((element: any) => {
  arrayInstrumentations[element] = function (this: unknown[], ...args: unknown[]) {
    // 暂停依赖收集
    pauseTracking();
    const res = (toRaw(this) as any)[element].apply(this, args);
    // 恢复依赖收集
    resumeTracking();
    return res;
  }
})


export default function (target: any, key: string | symbol, receiver: any) {
  if(key === RAW) return target
  track(target, TrackOpTypes.GET, key);

  // 如果是读取数组的方法
  if (Array.isArray(target) && arrayInstrumentations.hasOwnProperty(key)) {
    return arrayInstrumentations[key as string];
  }

  const res = Reflect.get(target, key, receiver);

  if (isObject(res)) {
    return reactive(res);
  }

  return res;
}